/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


(function( $ ){
    
    cruise = {
        fillips:{}  
    };
    

    var methods = {
        draw:function(cruisedl){
            if(cruisedl==null) return null;
            return parseCruise(this, cruisedl);
        }
    };
    
    function parseHandler(handler){
        var h = {};
        h.event = handler.match(/~[^-#]+/g);
        h.target = handler.match(/[#.][^-]+/g);
        h.func = handler.match(/->[^-#]+/g);
        return h;
    }
    
    function parseSelector(selector){
        var s = {};
        s.classes = selector.match(/\.[^\.#]+/g);
        if(s.classes){
            $.each(s.classes, function(i,v){    //remove the "."
                s.classes[i] = v.slice(1); 
            });
        }else{
            s.classes = [];
        }
        
        var ids = selector.match(/#[^\.#]+/g);
        s.id = ids ? ids[0].slice(1) : "ele_" + (eCount++); //remove the "#" and generate an id if none is found
        
        var tags = selector.match(/^([^\.#]+)/g); 
        tag = tags ? tags[0] : "div"; //If there is no tag assume it is a div

        if(tag.indexOf("input")!=-1){
            var ele = tag.split("|");
            s.tag = ele[0];
            s.type = ele.length==2 ? ele[1] : "text";
        }else{
            s.tag = tag;
        }
        
        return s;
    };

    function applyHandler(parent, key, value){
        parent.bind(key.slice(1),function(){
            var f = value["@action"];
            var t = value["@target"];
            //var p = Array.prototype.slice.call(value["@params"]);
            var p = value["@params"];
            if(t){
                var j = $(t);
                j[f].apply(j,p);
            }else{
                window[f].apply(null,p);
            }
        });
    }
    
    function parseCruise(parent,cruisedl){
        var children = new Array();
        var eleFillips = new Array();
        //Loop over every property in the CruiseDL object
        
        $.each(cruisedl, function(key,value){
            var tid = key.charAt(0); //Get the type identifier
            if(tid=="@"){                                           //If the TID is @ then the descriptor is an attribute
                parent.attr(key.slice(1),value);
            }else if(tid=="~"){
                var handler = parseHandler(key);
                if(typeof value === "object" && value instanceof Array){
                    var params = value;
                    value = {
                        "@params":params
                    };
                }
                if(handler.func != null && handler.func.length > 0) value["@action"] = handler.func[0].slice(2);
                if(handler.target != null && handler.target.length > 0) value["@target"] = handler.target[0];
                applyHandler(parent, handler.event[0], value);
            }else if(key == "html"){                                //If key is "html" simply append it to the parent
                parent.html(value);
            }else if(tid=="-"){
                if(key.charAt(1)==">"){                             //if the key starts with ->, then it means this a processor call
                    eleFillips.push({
                        "fillip":key.slice(2),
                        "params":value
                    });                    
                }
            }else{                                                  // If it is none of the above then it is should be an element
                var s = parseSelector(key);
                
                //TODO: Should we check if it is a valid tag???
                
                /* value.tag = s.tag; */
                value["@id"] = s.id;
                
                if(s.classes.length > 0){
                    if(value["@class"] && value["@class"]!=null){
                        value["@class"] = " " + s.classes.join(" ");
                    }else{
                        value["@class"] = s.classes.join(" ");
                    }
                }
                s.type = s.type ? s.type : value["@type"];
                delete value["@type"];
                
                if(s.tag == "input"){
                    if(!value["@name"]){
                        value["@name"] = s.id;
                    }
                    
                    if(!value["@value"] && (s.type == "button" || s.type == "submit" || s.type == "reset")){
                        value["@value"] = s.id;
                    }
                }
                
                children.push({
                    "tag":s.tag,
                    "type": s.type,
                    "cdl":value
                });
                
            }
        });
        
        
        //Execute all "before" fillips
        $.each(eleFillips,function(i,v){
            if(cruise.fillips[v.fillip] && cruise.fillips[v.fillip].order == "before"){
                cruise.fillips[v.fillip].process(parent, children, v.params);
            } 
        });

        //Create the elements in the DOM
        $.each(children,function(i,v){
            var dnode = document.createElement(v.tag);

            var cdl = children[i].cdl;
           
            if(v.type) dnode.type = v.type;
            jnode = $(dnode);
            jnode.appendTo(parent);
            children[i].base = jnode;
        });
        
        //Execute all the after fillips
      
        
        //Process the child cruisedls
        $.each(children,function(i,v){
            parseCruise(v.base,v.cdl);
        });
        
        return this;
        
    };
    
    
    var eCount = 0;

    $.fn.cruise = function(method) {
        // Method calling logic
        if ( methods[method] ) {
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.draw.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
        }  
    }

})( jQuery );


